from abc import ABC
import os

from Server.Handlers.basic import FileServerRequestHandler, Param
from Server.Utils import htmlUtils, media, fileType
from Server import const


class SonHandle(FileServerRequestHandler, ABC):
    def get(self, url):  # url 形式来自路由表设置（router.py），路由表路由后面的部分
        routeFrom, route = self.getRfAndRoute(url)
        filePath = Param.RoutePath[routeFrom] + '/' + url

        if not os.path.exists(filePath):  # 请求位置不存在返回 404
            self.handlePathNotExists(filePath)

        elif self.needHide(filePath):  # 隐藏内容
            self.handleHiddenPath(filePath)

        elif os.path.isdir(filePath):  # 目录则构建成HTML返回
            fullUrl = self.request.full_url()
            if not fullUrl.endswith('/'):
                self.redirect(fullUrl + '/')
                return
            self.handleMakeDirHtml(filePath, route, routeFrom)

        else:  # 文件处理
            # 获取文件类型
            ty = fileType.getFileType(filePath)
            if ty == fileType.Type.IMAGE:  # 图片
                self.handleImage(filePath)

            elif ty == fileType.Type.AUDIO:  # 音频
                self.handleAudio(filePath, route, routeFrom)

            else:  # 其他普通文件正常读取并返回
                self.handleNormal(filePath)

    def handleImagePreview(self, filePath: str, quality: int = 10, scale: float = 1):
        """
        处理预览图请求

        :param filePath: 源文件本地路径
        :param quality: 预览图片质量，0~99，数字越小越模糊，压缩的越厉害，默认为 10
        :param scale: 图片缩放比例（0~1），默认为1，不缩放
        :return:
        """
        ft = fileType.getFileType(filePath)
        # 源文件不存在或者是需要隐藏的文件则返回404
        if not os.path.exists(filePath) or fileType.isHiddenPath(filePath, Param.HiddenConfig):
            self.set_status(404)
            self.write(media.read404image())
            self.setContentType('image/png')
        elif ft == fileType.Type.IMAGE:  # 图片预览图
            self.write(media.imageCompress(filePath, quality, scale))
            self.setContentType(fileType.getContentType(filePath))
        else:  # 啥也不是
            self.responseCodeHtml(400)

    def handleImage(self, imagePath: str):
        """

        :param imagePath:
        :return:
        """
        args = self.request.arguments
        if not args:  # 没有参数才返回源数据
            self.handleReadFile(imagePath)
        elif 'act' in args:
            value = self.get_argument('act')
            if value == 'pre':  # 参数 act 的值为 pre (PREview)
                quality = self.getArgumentWithDefaultAndType('qy', 10, 'int')
                scale = self.getArgumentWithDefaultAndType('sc', 1, 'float')
                self.handleImagePreview(imagePath, quality, scale)
            else:
                self.responseCodeHtml(400)
        else:
            self.responseCodeHtml(400)

    def handleAudio(self, audioPath: str, route: str, routeFrom: str):
        """
        处理音频（音频文件必须存在）

        :param audioPath:
        :param route:
        :param routeFrom:
        :return:
        """
        args = self.request.arguments
        if not args:  # 没有参数才返回播放音频页面
            self.write(htmlUtils.makeAudioHtml(self, route, Param.ProxyUrl, routeFrom))
            self.setContentType('text/html')
        elif 'act' in args:
            value = self.get_argument('act')
            if value == 'dl':  # 参数 act 的值为 dl (DownLoad)
                self.handleReadFile(audioPath)
            elif value == 'pl':  # 参数 act 的值为 pl (PLay)
                self.handleReadFile(audioPath)
            else:
                self.responseCodeHtml(400)
        else:
            self.responseCodeHtml(400)

    def handleNormal(self, filepath: str):
        """

        :param filepath:
        :return:
        """
        args = self.request.arguments
        if not args:  # 没有参数才返回源数据
            self.handleReadFile(filepath, '', dl=False)
        elif 'act' in args:
            value = self.get_argument('act')
            if value == 'tl':  # 参数 act 的值为 tl (TransLate)，翻译
                self.handleReadFile(filepath, '', tl=True, dl=False)
            else:
                self.responseCodeHtml(400)
        else:
            self.responseCodeHtml(400)
